// cmd/vmctl/commands/network.go
package commands

import (
	"context"
	"encoding/json"
	"fmt"
	"strings"

	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"

	"virt-manager-go/internal/domain"
)

func NewNetworkCommand(logger *logrus.Logger) *cobra.Command {
	cmd := &cobra.Command{
		Use:   "network",
		Short: "Manage virtual networks",
	}

	cmd.AddCommand(
		newNetworkListCommand(logger),
		newNetworkCreateCommand(logger),
		newNetworkDeleteCommand(logger),
		newNetworkStartCommand(logger),
		newNetworkStopCommand(logger),
		newNetworkDHCPCommand(logger),
	)

	return cmd
}

// vmctl network list
func newNetworkListCommand(logger *logrus.Logger) *cobra.Command {
	var connID string

	cmd := &cobra.Command{
		Use:   "list",
		Short: "List virtual networks",
		RunE: func(cmd *cobra.Command, args []string) error {
			apiClient := getAPIClient(logger)
			if connID == "" {
				connID = getDefaultConnection(apiClient)
			}

			ctx := context.Background()
			resp, err := apiClient.Get(ctx, fmt.Sprintf("/api/v1/connections/%s/networks", connID))
			if err != nil {
				return err
			}

			var result struct {
				Data []domain.NetworkInfo `json:"data"`
			}
			if err := json.Unmarshal(resp, &result); err != nil {
				return err
			}

			// 获取输出格式并格式化输出
			outputFormat := GetOutputFormat(cmd.Flag("output").Value.String())
			formatter := NewFormatter(outputFormat)
			return formatter.FormatNetworkList(result.Data)
		},
	}

	cmd.Flags().StringVarP(&connID, "connection", "c", "", "Connection ID")
	return cmd
}

// vmctl network create
func newNetworkCreateCommand(logger *logrus.Logger) *cobra.Command {
	var (
		connID    string
		name      string
		forward   string
		address   string
		netmask   string
		dhcpStart string
		dhcpEnd   string
		bridge    string
	)

	cmd := &cobra.Command{
		Use:   "create",
		Short: "Create a virtual network",
		Example: `  vmctl network create --name mynet --address 192.168.100.1 --netmask 255.255.255.0 \
    --dhcp-start 192.168.100.10 --dhcp-end 192.168.100.100 --forward nat`,
		RunE: func(cmd *cobra.Command, args []string) error {
			apiClient := getAPIClient(logger)
			if connID == "" {
				connID = getDefaultConnection(apiClient)
			}

			config := domain.NetworkConfig{
				Name:    name,
				Forward: domain.ForwardMode(forward),
				Bridge:  bridge,
				IP: []domain.NetworkIPConfig{
					{
						Address: address,
						Netmask: netmask,
					},
				},
			}

			if dhcpStart != "" && dhcpEnd != "" {
				config.IP[0].DHCP = &domain.NetworkDHCPConfig{
					Start: dhcpStart,
					End:   dhcpEnd,
				}
			}

			ctx := context.Background()
			resp, err := apiClient.Post(ctx, fmt.Sprintf("/api/v1/connections/%s/networks", connID), config)
			if err != nil {
				return err
			}

			var result struct {
				Data domain.NetworkInfo `json:"data"`
			}
			if err := json.Unmarshal(resp, &result); err != nil {
				return err
			}

			fmt.Printf("✓ Network '%s' created\n", result.Data.Name)
			return nil
		},
	}

	cmd.Flags().StringVarP(&connID, "connection", "c", "", "Connection ID")
	cmd.Flags().StringVarP(&name, "name", "n", "", "Network name (required)")
	cmd.Flags().StringVar(&forward, "forward", "nat", "Forward mode (nat, route, bridge, none)")
	cmd.Flags().StringVar(&address, "address", "", "IP address (required)")
	cmd.Flags().StringVar(&netmask, "netmask", "", "Netmask (required)")
	cmd.Flags().StringVar(&dhcpStart, "dhcp-start", "", "DHCP range start")
	cmd.Flags().StringVar(&dhcpEnd, "dhcp-end", "", "DHCP range end")
	cmd.Flags().StringVar(&bridge, "bridge", "", "Bridge name")

	cmd.MarkFlagRequired("name")
	cmd.MarkFlagRequired("address")
	cmd.MarkFlagRequired("netmask")

	return cmd
}

// vmctl network delete
func newNetworkDeleteCommand(logger *logrus.Logger) *cobra.Command {
	var (
		connID  string
		confirm bool
	)

	cmd := &cobra.Command{
		Use:   "delete <network-name>",
		Short: "Delete a virtual network",
		Args:  cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			apiClient := getAPIClient(logger)
			if connID == "" {
				connID = getDefaultConnection(apiClient)
			}

			networkName := args[0]

			if !confirm {
				fmt.Printf("Delete network '%s'? [y/N]: ", networkName)
				var response string
				fmt.Scanln(&response)
				if strings.ToLower(response) != "y" {
					return nil
				}
			}

			ctx := context.Background()
			_, err := apiClient.Delete(ctx, fmt.Sprintf("/api/v1/connections/%s/networks/%s", connID, networkName))
			if err != nil {
				return err
			}

			fmt.Printf("✓ Network '%s' deleted\n", networkName)
			return nil
		},
	}

	cmd.Flags().StringVarP(&connID, "connection", "c", "", "Connection ID")
	cmd.Flags().BoolVarP(&confirm, "yes", "y", false, "Skip confirmation")
	return cmd
}

// vmctl network start
func newNetworkStartCommand(logger *logrus.Logger) *cobra.Command {
	var connID string

	cmd := &cobra.Command{
		Use:   "start <network-name>",
		Short: "Start a virtual network",
		Args:  cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			apiClient := getAPIClient(logger)
			if connID == "" {
				connID = getDefaultConnection(apiClient)
			}

			networkName := args[0]
			ctx := context.Background()
			_, err := apiClient.Post(ctx, fmt.Sprintf("/api/v1/connections/%s/networks/%s/start", connID, networkName), nil)
			if err != nil {
				return err
			}

			fmt.Printf("✓ Network '%s' started\n", networkName)
			return nil
		},
	}

	cmd.Flags().StringVarP(&connID, "connection", "c", "", "Connection ID")
	return cmd
}

// vmctl network stop
func newNetworkStopCommand(logger *logrus.Logger) *cobra.Command {
	var connID string

	cmd := &cobra.Command{
		Use:   "stop <network-name>",
		Short: "Stop a virtual network",
		Args:  cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			apiClient := getAPIClient(logger)
			if connID == "" {
				connID = getDefaultConnection(apiClient)
			}

			networkName := args[0]
			ctx := context.Background()
			_, err := apiClient.Post(ctx, fmt.Sprintf("/api/v1/connections/%s/networks/%s/stop", connID, networkName), nil)
			if err != nil {
				return err
			}

			fmt.Printf("✓ Network '%s' stopped\n", networkName)
			return nil
		},
	}

	cmd.Flags().StringVarP(&connID, "connection", "c", "", "Connection ID")
	return cmd
}

// vmctl network dhcp-leases
func newNetworkDHCPCommand(logger *logrus.Logger) *cobra.Command {
	var connID string

	cmd := &cobra.Command{
		Use:   "dhcp-leases <network-name>",
		Short: "Show DHCP leases for a network",
		Args:  cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			apiClient := getAPIClient(logger)
			if connID == "" {
				connID = getDefaultConnection(apiClient)
			}

			networkName := args[0]
			ctx := context.Background()
			resp, err := apiClient.Get(ctx, fmt.Sprintf("/api/v1/connections/%s/networks/%s/dhcp-leases", connID, networkName))
			if err != nil {
				return err
			}

			var result struct {
				Data []domain.DHCPLease `json:"data"`
			}
			if err := json.Unmarshal(resp, &result); err != nil {
				return err
			}

			// 获取输出格式并格式化输出
			outputFormat := GetOutputFormat(cmd.Flag("output").Value.String())
			formatter := NewFormatter(outputFormat)
			return formatter.FormatDHCPLeases(result.Data)
		},
	}

	cmd.Flags().StringVarP(&connID, "connection", "c", "", "Connection ID")
	return cmd
}

// ============================================
// cmd/vmctl/commands/connection.go
// ============================================

func NewConnectionCommand(logger *logrus.Logger) *cobra.Command {
	cmd := &cobra.Command{
		Use:     "connection",
		Short:   "Manage libvirt connections",
		Aliases: []string{"conn"},
	}

	cmd.AddCommand(
		newConnectionListCommand(logger),
		newConnectionAddCommand(logger),
		newConnectionRemoveCommand(logger),
	)

	return cmd
}

// vmctl connection list
func newConnectionListCommand(logger *logrus.Logger) *cobra.Command {
	cmd := &cobra.Command{
		Use:   "list",
		Short: "List all connections",
		RunE: func(cmd *cobra.Command, args []string) error {
			apiClient := getAPIClient(logger)
			ctx := context.Background()
			resp, err := apiClient.Get(ctx, "/api/v1/connections")
			if err != nil {
				return err
			}

			var result struct {
				Data []domain.ConnectionInfo `json:"data"`
			}
			if err := json.Unmarshal(resp, &result); err != nil {
				return err
			}

			// 获取输出格式并格式化输出
			outputFormat := GetOutputFormat(cmd.Flag("output").Value.String())
			formatter := NewFormatter(outputFormat)
			return formatter.FormatConnectionList(result.Data)
		},
	}

	return cmd
}

// vmctl connection add
func newConnectionAddCommand(logger *logrus.Logger) *cobra.Command {
	var (
		uri      string
		readOnly bool
	)

	cmd := &cobra.Command{
		Use:   "add",
		Short: "Add a new connection",
		Example: `  vmctl connection add --uri qemu:///system
  vmctl connection add --uri qemu+ssh://user@host/system
  vmctl connection add --uri qemu:///system --read-only`,
		RunE: func(cmd *cobra.Command, args []string) error {
			apiClient := getAPIClient(logger)
			req := map[string]interface{}{
				"uri":       uri,
				"read_only": readOnly,
			}

			ctx := context.Background()
			resp, err := apiClient.Post(ctx, "/api/v1/connections", req)
			if err != nil {
				return err
			}

			var result struct {
				ConnectionID string `json:"connection_id"`
			}
			if err := json.Unmarshal(resp, &result); err != nil {
				return err
			}

			fmt.Printf("✓ Connection added: %s\n", result.ConnectionID)
			return nil
		},
	}

	cmd.Flags().StringVarP(&uri, "uri", "u", "", "Connection URI (required)")
	cmd.Flags().BoolVar(&readOnly, "read-only", false, "Read-only connection")

	cmd.MarkFlagRequired("uri")
	return cmd
}

// vmctl connection remove
func newConnectionRemoveCommand(logger *logrus.Logger) *cobra.Command {
	cmd := &cobra.Command{
		Use:   "remove <connection-id>",
		Short: "Remove a connection",
		Args:  cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			apiClient := getAPIClient(logger)
			connID := args[0]

			ctx := context.Background()
			_, err := apiClient.Delete(ctx, fmt.Sprintf("/api/v1/connections/%s", connID))
			if err != nil {
				return err
			}

			fmt.Printf("✓ Connection removed: %s\n", connID)
			return nil
		},
	}

	return cmd
}

// ============================================
// cmd/vmctl/commands/migration.go
// ============================================

func NewMigrationCommand(logger *logrus.Logger) *cobra.Command {
	cmd := &cobra.Command{
		Use:   "migrate",
		Short: "Migrate virtual machines",
	}

	cmd.AddCommand(
		newMigrateStartCommand(logger),
		newMigrateStatusCommand(logger),
		newMigrateCancelCommand(logger),
	)

	return cmd
}

// vmctl migrate start
func newMigrateStartCommand(logger *logrus.Logger) *cobra.Command {
	var (
		connID     string
		destURI    string
		live       bool
		compressed bool
	)

	cmd := &cobra.Command{
		Use:     "start <vm-name>",
		Short:   "Start VM migration",
		Args:    cobra.ExactArgs(1),
		Example: `  vmctl migrate start ubuntu-vm --dest qemu+ssh://user@host/system --live`,
		RunE: func(cmd *cobra.Command, args []string) error {
			apiClient := getAPIClient(logger)
			if connID == "" {
				connID = getDefaultConnection(apiClient)
			}

			vmName := args[0]

			req := map[string]interface{}{
				"dest_uri": destURI,
				"config": map[string]interface{}{
					"live":       live,
					"compressed": compressed,
				},
			}

			ctx := context.Background()
			resp, err := apiClient.Post(ctx,
				fmt.Sprintf("/api/v1/connections/%s/vms/%s/migrate", connID, vmName),
				req)
			if err != nil {
				return err
			}

			var result struct {
				Data domain.MigrationJob `json:"data"`
			}
			if err := json.Unmarshal(resp, &result); err != nil {
				return err
			}

			fmt.Printf("✓ Migration started\n")
			fmt.Printf("  Job ID: %s\n", result.Data.ID)
			fmt.Printf("  Status: %s\n", result.Data.Status)
			fmt.Printf("\nMonitor with: vmctl migrate status %s\n", result.Data.ID)
			return nil
		},
	}

	cmd.Flags().StringVarP(&connID, "connection", "c", "", "Connection ID")
	cmd.Flags().StringVarP(&destURI, "dest", "d", "", "Destination URI (required)")
	cmd.Flags().BoolVar(&live, "live", true, "Live migration")
	cmd.Flags().BoolVar(&compressed, "compressed", false, "Compressed migration")

	cmd.MarkFlagRequired("dest")
	return cmd
}

// vmctl migrate status
func newMigrateStatusCommand(logger *logrus.Logger) *cobra.Command {
	cmd := &cobra.Command{
		Use:   "status <job-id>",
		Short: "Check migration status",
		Args:  cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			apiClient := getAPIClient(logger)
			jobID := args[0]

			ctx := context.Background()
			resp, err := apiClient.Get(ctx, fmt.Sprintf("/api/v1/migrations/%s", jobID))
			if err != nil {
				return err
			}

			var result struct {
				Data domain.MigrationJob `json:"data"`
			}
			if err := json.Unmarshal(resp, &result); err != nil {
				return err
			}

			fmt.Printf("Migration Job: %s\n", result.Data.ID)
			fmt.Printf("  VM:       %s\n", result.Data.VMName)
			fmt.Printf("  Status:   %s\n", result.Data.Status)
			fmt.Printf("  Progress: %.1f%%\n", result.Data.Progress)

			if result.Data.DataTotal > 0 {
				fmt.Printf("  Data:     %s / %s\n",
					formatBytes(result.Data.DataTotal-result.Data.DataRemaining),
					formatBytes(result.Data.DataTotal))
			}

			if result.Data.Error != "" {
				fmt.Printf("  Error:    %s\n", result.Data.Error)
			}

			return nil
		},
	}

	return cmd
}

// vmctl migrate cancel
func newMigrateCancelCommand(logger *logrus.Logger) *cobra.Command {
	cmd := &cobra.Command{
		Use:   "cancel <job-id>",
		Short: "Cancel migration",
		Args:  cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			apiClient := getAPIClient(logger)
			jobID := args[0]

			ctx := context.Background()
			_, err := apiClient.Post(ctx, fmt.Sprintf("/api/v1/migrations/%s/cancel", jobID), nil)
			if err != nil {
				return err
			}

			fmt.Printf("✓ Migration cancelled: %s\n", jobID)
			return nil
		},
	}

	return cmd
}

// ============================================
// cmd/vmctl/commands/event.go
// ============================================

func NewEventCommand(logger *logrus.Logger) *cobra.Command {
	cmd := &cobra.Command{
		Use:   "events",
		Short: "Monitor system events",
	}

	cmd.AddCommand(
		newEventsWatchCommand(logger),
		newEventsHistoryCommand(logger),
	)

	return cmd
}

// vmctl events watch
func newEventsWatchCommand(logger *logrus.Logger) *cobra.Command {
	var (
		eventTypes []string
		vmName     string
	)

	cmd := &cobra.Command{
		Use:   "watch",
		Short: "Watch events in real-time",
		Example: `  vmctl events watch
  vmctl events watch --type vm,network
  vmctl events watch --vm ubuntu-vm`,
		RunE: func(cmd *cobra.Command, args []string) error {
			fmt.Println("Watching events... (Press Ctrl+C to exit)")
			fmt.Println()

			// 这里应该实现 SSE 客户端
			// 为简化示例，仅显示提示
			fmt.Println("Event monitoring would stream here...")
			fmt.Println("(Full SSE implementation required)")

			return nil
		},
	}

	cmd.Flags().StringSliceVar(&eventTypes, "type", []string{}, "Event types to watch")
	cmd.Flags().StringVar(&vmName, "vm", "", "Filter by VM name")
	return cmd
}

// vmctl events history
func newEventsHistoryCommand(logger *logrus.Logger) *cobra.Command {
	var limit int

	cmd := &cobra.Command{
		Use:   "history",
		Short: "Show event history",
		RunE: func(cmd *cobra.Command, args []string) error {
			apiClient := getAPIClient(logger)
			ctx := context.Background()
			resp, err := apiClient.Get(ctx, fmt.Sprintf("/api/v1/events/history?limit=%d", limit))
			if err != nil {
				return err
			}

			var result struct {
				Data []domain.Event `json:"data"`
			}
			if err := json.Unmarshal(resp, &result); err != nil {
				return err
			}

			// 获取输出格式并格式化输出
			outputFormat := GetOutputFormat(cmd.Flag("output").Value.String())
			formatter := NewFormatter(outputFormat)
			return formatter.FormatEventList(result.Data)
		},
	}

	cmd.Flags().IntVarP(&limit, "limit", "n", 50, "Number of events to show")
	return cmd
}

// ============================================
// Makefile for building CLI
// ============================================

/*
# Makefile

.PHONY: build install clean test

BINARY_NAME=vmctl
VERSION=1.0.0
BUILD_DIR=bin

build:
	@echo "Building $(BINARY_NAME)..."
	@mkdir -p $(BUILD_DIR)
	go build -o $(BUILD_DIR)/$(BINARY_NAME) -ldflags="-X main.Version=$(VERSION)" cmd/vmctl/main.go
	@echo "✓ Build complete: $(BUILD_DIR)/$(BINARY_NAME)"

build-all:
	@echo "Building for multiple platforms..."
	@mkdir -p $(BUILD_DIR)
	GOOS=linux GOARCH=amd64 go build -o $(BUILD_DIR)/$(BINARY_NAME)-linux-amd64 cmd/vmctl/main.go
	GOOS=darwin GOARCH=amd64 go build -o $(BUILD_DIR)/$(BINARY_NAME)-darwin-amd64 cmd/vmctl/main.go
	GOOS=darwin GOARCH=arm64 go build -o $(BUILD_DIR)/$(BINARY_NAME)-darwin-arm64 cmd/vmctl/main.go
	GOOS=windows GOARCH=amd64 go build -o $(BUILD_DIR)/$(BINARY_NAME)-windows-amd64.exe cmd/vmctl/main.go
	@echo "✓ Multi-platform build complete"

install: build
	@echo "Installing $(BINARY_NAME)..."
	sudo cp $(BUILD_DIR)/$(BINARY_NAME) /usr/local/bin/
	@echo "✓ Installed to /usr/local/bin/$(BINARY_NAME)"

uninstall:
	@echo "Uninstalling $(BINARY_NAME)..."
	sudo rm -f /usr/local/bin/$(BINARY_NAME)
	@echo "✓ Uninstalled"

clean:
	@echo "Cleaning build artifacts..."
	rm -rf $(BUILD_DIR)
	@echo "✓ Clean complete"

test:
	go test -v ./...

.DEFAULT_GOAL := build
*/
